// Hashing Project
// Akshay Gupta
// 2010010 BTECH



# include <stdio.h>
# include <stdlib.h>
# include <string.h>
#define N 10

struct node  // Data structure  to from the bucket or hash table
	{ 
	int key[N];
	int password[N];
	struct node *next;
	}*first=NULL,*temp=NULL,*nnode=NULL,*current=NULL; // Linled list






int divhash(int key)  //Hashing By Division
	{
	return key%7;
	}

int mhash(int key) //Hashing using multiplication
	{
	float k=key;int s=(0.5*k),j=s%N;
	int f=N*j;
	return f;
	}
		

int ldhash(int key,int i) // Hashing using linear probing Division
	{
	return ((divhash(key)+i)%N);
	}


int lmhash(int key,int i) // Hashing using linear probing Multiplication
	{
	return ((mhash(key)+i)%N);
	}
int uhash(int key) // Univeral Hashing
	{
	int sel=(random()%5);
	switch(sel)
		{
		case 0:return ((2*key+5)%17)%N ;break;
		case 1:return ((7*key+15)%23)%N;break;
		case 2:return ((3*key+1)%11)%N ;break;
		case 3:return ((9*key+7)%29)%N ;break;
		case 4:return ((1*key+6)%31)%N ;break;
		}
	}	


int luhash(int key,int i) // Hashing using linear probing Universal hash
	{
	return ((uhash(key)+i)%N);
	}





int hashinsert(int keyu,int keyp,int choice,struct node *current)  // To insert using hashing function chosen by the user
	{
	int i=0,j;
	do
		{
		switch(choice)
			{
			case 1:j=ldhash(keyu,i);break;
			case 2:j=lmhash(keyu,i);break;
			case 3:j=luhash(keyu,i);break;
			}
			
		
		if(!current->key[j])           // Slot Check for insertion
			{
			current->key[j]=keyu;
			current->password[j]=keyp;	
			return 1;
			}
		else
			i=i+1;              // Probe increment
		}while(i<N);
	return 0;
	}


int match(int keyu,int keyp,int choice)
	{
	temp=first;
	int check=0;
	while(temp!=NULL)
	{
	int i=0,j;
	do
		{
		switch(choice)
			{
			case 1:j=ldhash(keyu,i);break;
			case 2:j=lmhash(keyu,i);break;
			case 3:j=luhash(keyu,i);break;
			}
		
		if((temp->key[j]==keyu)&&(temp->password[j]==keyp))  // To check userid and password
			{
			printf("\nCorrect Password\n");
			return 1;
			if(temp->key[j]==keyu)
				check=1;
			}	
		else
			i++;							// Probe increment
		}while((!temp->key[j])|(i<N));
	temp=temp->next;
	}
	if(check)
		{
		printf("\nIncorrect Password\n");
		return 0;
		}
	else
		{
		printf("\nNo such userid exists\n");
		return 0;
		}
	}


void show()					// To show the contents of the hash table not included in main
	{
	temp=first;
	while(temp!=NULL)
	{
	int i=0;
	for(;i<N;i++)
		printf("%d  %d \n",temp->key[i],temp->password[i]);
	temp=temp->next;
	}
	return;
	}

int keygen(char  *userid)
	{
	int key=0,i;
	char *temp1;
	temp1=userid;
	for(i=1;i<=strlen(temp1);i++,temp1++)	// Converting the given userid into an unique key
		key+=((int)(*temp1))*i;
	return key;
	}



int main()
	
	{
	int keyu,keyp,check=1,choice,i=0,ans;
	
	char *userid=NULL;
	char *passw=NULL;
	passw=(char*)malloc(11);
	userid=(char*)malloc(11);
	printf("Enter hashing function of your choice from the given menu\n");
	printf("1: Hashing using division \n");
	printf("2: Hashing using multiplication\n");
	printf("3: Universal hashing\n");
	scanf("%d",&choice);
	
	char fname[30];
	printf("Enter file address\n");
	scanf("%s",fname);
	

	first=malloc(sizeof(struct node));
	current=first;
	first->next=NULL;
	
	for(i=0;i<N;i++)
		current->key[i]=0;
	
	FILE *fp;
	fp=fopen(fname,"r");
	fscanf(fp,"%s",userid);fscanf(fp,"%s",passw);
	while(!feof(fp))
		{
		fscanf(fp,"%s",userid);	
		fscanf(fp,"%s",passw);
		keyu=keygen(userid);
		keyp=keygen(passw);
		if(check)
			{
			check=hashinsert(keyu,keyp,choice,current);
			}
		else
			{
			nnode=malloc(sizeof(struct node));
			current->next=nnode;
			
			current=nnode;
			for(i=0;i<N;i++)
				current->key[i]=0;
			nnode->next=NULL;
			check=1;
			check=hashinsert(keyu,keyp,choice,current);
			}
		}
	fclose(fp);
	int k=0;
	do
		{
		printf("\nEnter userid: ");
		scanf("%s",userid);
		printf("Enter password: ");
		scanf("%s",passw);
		keyu=keygen(userid);
		keyp=keygen(passw);
		ans=match(keyu,keyp,choice);
		if(!ans)
			k++;
		else
			return 0;
		}while(k<3);
	printf("\nAccess denied too many tries\n");	
	
	return 0;
	}
